/*
	GadgetECM.cpp
	(c)2000 Palestar, Richard Lyle
*/


#include "Debug/Assert.h"
#include "VerbGadgetOff.h"
#include "GadgetECM.h"
#include "GameContext.h"
#include "Resource.h"
#include "StructureDefense.h"

//----------------------------------------------------------------------------

const int ECM_UPDATE_RATE = TICKS_PER_SECOND * 5;

//----------------------------------------------------------------------------

IMPLEMENT_ABSTRACT_FACTORY( GadgetECM, NounGadget ); 
REGISTER_FACTORY_KEY( GadgetECM, 4137137660558874319 );

BEGIN_ABSTRACT_PROPERTY_LIST( GadgetECM, NounGadget );
END_PROPERTY_LIST();

GadgetECM::GadgetECM() : m_nUpdateTick( 0 )
{}

//----------------------------------------------------------------------------

void GadgetECM::render( RenderContext &context, 
				const Matrix33 & frame, 
				const Vector3 & position )
{
	if ( active() )
	{
		Scene * pUseEffect = useEffect();
		if ( pUseEffect != NULL )
			pUseEffect->render( context, frame, position );
	}
}

//----------------------------------------------------------------------------

void GadgetECM::release()
{
	NounGadget::release();

	// release pointers
	m_Affect.release();
}

void GadgetECM::simulate( dword nTick )
{
	if ( active() && nTick >= m_nUpdateTick )
	{
		m_nUpdateTick = nTick + ECM_UPDATE_RATE;
		m_Affect.release();

		// affect the ECM of all objects within range
		Array< GameContext::NounCollision > nouns;
		if ( context()->proximityCheck( worldPosition(), range(), nouns ) )
		{
			for(int i=0;i<nouns.size();i++)
			{
				NounGame * pAffect = WidgetCast<NounGame>( nouns[ i ].pNoun );
				if ( pAffect != NULL && pAffect->enableECM() )
					m_Affect.push( pAffect );
			}
		}
	}

	NounGadget::simulate( nTick );
}

//----------------------------------------------------------------------------

NounGadget::Type GadgetECM::type() const
{
	return SPECIAL_DEFENSIVE;
}

dword GadgetECM::hotkey() const
{
	return 'M';
}

bool GadgetECM::usable( Noun * pTarget, bool shift ) const
{
	if ( active() )
		return true;	// always allow it to be turned off...
	if (! NounGadget::usable( pTarget, shift ) )
		return false;
	if ( destroyed() )
		return false;
	return true;
}

bool GadgetECM::useActive() const
{
	return active();
}

void GadgetECM::use( dword when, Noun * pTarget, bool shift)
{
	NounGadget::use( when, pTarget, shift );

	// set the device active
	setFlags( FLAG_ACTIVE, !active() );
	message( CharString().format( "<color;ffffff>Tactical: %s %s.", name(), active() ? "Active" : "Inactive" ) ); 
}

int GadgetECM::useEnergy( dword nTick, int energy )
{
	if ( active() )
	{
		// modify the ECM on the affected ships
		for(int i=0;i<m_Affect.size();i++)
		{
			NounGame * pAffect = WidgetCast<NounGame>( m_Affect[i] );
			if ( pAffect != NULL )
			{
				float fDistance = (worldPosition() - pAffect->worldPosition()).magnitude();
				if ( fDistance < range() )
					pAffect->addSignature( nTick, -((strength() * (range() - fDistance)) / range()) );
			}
		}

		energy -= energyCost();
		if ( (destroyed() || energy <= 0) && isLocal() )
			Verb::Ref( new VerbGadgetOff( this ) );
	}


	return energy;
}

bool GadgetECM::updateLogic()
{
	if ( WidgetCast<NounShip>( parent() ) )
	{
		NounShip * pShip = (NounShip *)parent();
		switch( pShip->command() )
		{
		case NounShip::EVADE:
			// turn on ECM
			if (! useActive() )
				pShip->useGadget( this, NULL, false );		
			break;
		default:
			// turn off ECM
			if ( useActive() )
				pShip->useGadget( this, NULL, false );
			break;
		}
		
		return true;
	}
	else if ( WidgetCast<StructureDefense>( parent() ) )
	{
		StructureDefense * pStructure = (StructureDefense *)parent();
		if ( pStructure->active() && !useActive() )
			pStructure->useGadget( NULL, this );		// turn on ECM 
		else if ( !pStructure->active() && useActive() )
			pStructure->useGadget( NULL, this );		// turn off ECM

		return true;
	}

	return true;
}

//----------------------------------------------------------------------------
// EOF
